package com.smasher.media

import android.content.Context
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.MediaPlayer
import android.media.MediaPlayer.OnPreparedListener
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import java.io.FileDescriptor
import java.io.IOException

/**
 * MediaPlayer
 * state change @see assets/img.png
 */
class AudioPlayer(context: Context, usage: Int, contentType: Int) : DefaultLifecycleObserver {
    private var mediaPlayer: MediaPlayer? = MediaPlayer()

    val attr: AudioAttributes = AudioAttributes.Builder()
        .setUsage(usage)
        .setContentType(contentType)
        .build()

    private val handler = Handler(Looper.getMainLooper())
    val am = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager

    private val lock = Any()

    private var currentPosition = 0 // 当前播放位置
    private var isPaused = false // 是否暂停

    private val preparedListener = object : OnPreparedListener {
        override fun onPrepared(mp: MediaPlayer) {
            handler.post {
                mp.start()
            }
        }
    }

    private val errorListener = object : MediaPlayer.OnErrorListener {
        override fun onError(
            mp: MediaPlayer?,
            what: Int,
            extra: Int
        ): Boolean {
            Log.e(TAG, "MediaPlayer error: what=$what, extra=$extra")
            return false
        }
    }


    constructor(context: Context) : this(
        context,
        AudioAttributes.USAGE_GAME,
        AudioAttributes.CONTENT_TYPE_MUSIC
    )

    private val completeListener = object : MediaPlayer.OnCompletionListener {
        override fun onCompletion(mediaPlayer: MediaPlayer?) {
            handler.post {
                mediaPlayer?.stop()
                mediaPlayer?.reset()
            }
        }
    }

    init {
        mediaPlayer?.setAudioAttributes(attr)
        mediaPlayer?.setOnPreparedListener(preparedListener)
        mediaPlayer?.setOnErrorListener(errorListener)
        mediaPlayer?.setOnCompletionListener(completeListener)
    }

    fun attach(lifecycleOwner: LifecycleOwner) {
        lifecycleOwner.lifecycle.addObserver(this)
    }

    /**
     * 播放本地音频文件
     * @param path 本地音频文件路径
     * @param isLoop 是否循环播放
     */
    fun playAudio(path: String, isLoop: Boolean) {
        synchronized(lock) {
            mediaPlayer?.let {
                if (it.isPlaying) {
                    it.stop()
                }
                it.reset()
                try {
                    it.setDataSource(path)
                } catch (e: IOException) {
                    Log.e(TAG, "Failed to set data source for local audio", e)
                    return
                }
                it.isLooping = isLoop
                it.prepareAsync()
            }
        }
    }

    /**
     * 播放文件描述符音频
     * @param fileDescriptor 文件描述符
     * @param isLoop 是否循环播放
     */
    fun playFile(fileDescriptor: FileDescriptor, isLoop: Boolean) {
        synchronized(lock) {
            mediaPlayer?.let {
                if (it.isPlaying) {
                    it.stop()
                }
                it.reset()
                try {
                    it.setDataSource(fileDescriptor)
                } catch (e: IOException) {
                    Log.e(TAG, "Failed to set data source for file descriptor audio", e)
                    return
                }
                it.isLooping = isLoop
                it.prepareAsync()
            }
        }
    }

    /**
     * 调整音量
     * @param volume 音量值（0-100）
     */
    fun setVolume(volume: Int) {
        synchronized(lock) {
            mediaPlayer?.let {
                val clampedVolume = volume.coerceIn(0, 100)
                val volumeRatio = clampedVolume / 100f
                it.setVolume(volumeRatio, volumeRatio)
            }
        }
    }

    /**
     * 暂停播放
     */
    fun pause() {
        synchronized(lock) {
            mediaPlayer?.let {
                if (it.isPlaying) {
                    it.pause()
                    currentPosition = it.currentPosition
                    isPaused = true
                }
            }
        }
    }

    /**
     * 恢复播放
     */
    fun resume() {
        synchronized(lock) {
            mediaPlayer?.let {
                if (isPaused) {
                    it.seekTo(currentPosition)
                    it.start()
                    isPaused = false
                }
            }
        }
    }

    /**
     * 释放资源
     */
    fun release() {
        synchronized(lock) {
            mediaPlayer?.let {
                try {
                    if (it.isPlaying) {
                        it.stop()
                    }
                    it.reset()
                    it.release()
                } catch (e: Exception) {
                    Log.e(TAG, "Failed to release MediaPlayer", e)
                } finally {
                    mediaPlayer = null
                }
            }
        }
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        release()
    }

    companion object {
        const val TAG = "AudioPlayer"
    }
}